﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FarseerPhysics.Common;
using Microsoft.Xna.Framework;
using FarseerPhysics.Common.ConvexHull;
using Input;
using Microsoft.Xna.Framework.Graphics;
using UtilityLibrary;

namespace MapLibrary
{
    public class EditorConvexHull :  List<EditorHullPoint>, ITransformable
    {

        private float rotation;

        public EditorConvexHull()
        {
            rotation = 0.0f;
        }

        public EditorConvexHull(Vertices verts)
        {
            rotation = 0.0f;
            BuildFromVertices(verts);
        }

        /// <summary>
        /// Converts the EditorConvexHull into Vertices
        /// </summary>
        /// <returns></returns>
        public Vertices ToVertices()
        {
            Vertices verts = new Vertices();

            foreach (EditorHullPoint hullPoint in this)
            {
                verts.Add(hullPoint.Point);
            }

            return verts;
        }

        public ITransformable GetHoveredNode(GameInput input, WorldViewport viewport)
        {
            foreach (EditorHullPoint hullPoint in this)
            {
                if (hullPoint.HasHover(input, viewport))
                    return hullPoint;
            }

            Vertices verts = ToVertices();
            Vector2 mousePos = viewport.ViewportCoordsToWorldCoords(input.GetMousePosition());

            if (verts.PointInPolygon(ref mousePos) == 1)
                return this;

            return null;
        }

        public new void Add(EditorHullPoint point)
        {
            base.Add(point);

            ResetToHull();
        }

        public void AddPoint(Vector2 point)
        {
            Add(new EditorHullPoint(point, this));
        }

        public void EditorDraw(SpriteBatch batch, WorldViewport viewport)
        {
            //Vertices verts = ToVertices();

            //PrimitiveBrush.RenderHull(
            //    batch,
            //    viewport.WorldToViewportAABB(verts.GetCollisionBox()));

            //foreach (EditorHullPoint point in this)
            //{
            //    point.EditorDraw(batch, viewport);
            //}

            //PrimitiveBrush.RenderHull(
            //    batch, 
            //    viewport.WorldToViewportCoords(verts));
            this.EditorDraw(batch, viewport, Color.Red);
        }

        public void EditorDraw(SpriteBatch batch, WorldViewport viewport, Color col)
        {
            Vertices verts = ToVertices();

            PrimitiveBrush.RenderHull(
                batch,
                viewport.WorldToViewportAABB(verts.GetCollisionBox()),
                col);

            foreach (EditorHullPoint point in this)
            {
                point.EditorDraw(batch, viewport, col);
            }

            PrimitiveBrush.RenderHull(
                batch,
                viewport.WorldToViewportCoords(verts), col);
        }

        /// <summary>
        /// Resets this set of points to be a convex hull.
        /// </summary>
        public void ResetToHull()
        {
            Vertices verts = ToVertices();
            if (!verts.IsConvex())
                BuildFromVertices(GiftWrap.GetConvexHull(verts));
        }

        private void BuildFromVertices(Vertices verts)
        {
            this.Clear();

            foreach (Vector2 vert in verts)
            {
                base.Add(new EditorHullPoint(vert, this));
            }
        }

        public void SetPosition(Vector2 Position)
        {
            Vertices verts = ToVertices();

            Vector2 pos = GetPosition();
            Vector2 translation = Position - GetPosition();

            verts.Translate(ref translation);

            BuildFromVertices(verts);
        }

        public Vector2 GetPosition()
        {
            Vertices verts = ToVertices();

            return verts.GetCentroid();
        }

        public void SetRotation(float rotation)
        {
            float rotDiff = rotation - this.rotation;
            this.rotation = rotation;

            Vertices verts = ToVertices();
            verts.Rotate(rotDiff);

            BuildFromVertices(verts);
        }

        public float GetRotation()
        {
            return rotation;
        }

        public void SetScale(Vector2 newScale)
        {
            throw new NotImplementedException();
        }

        public Vector2 GetScale()
        {
            return Vector2.UnitX + Vector2.UnitY;
        }

        public Vector2 GetCenter()
        {
            return GetPosition();
        }

        public bool IsActive()
        {
            return true;
        }
    }
}
